using System;
using SimpleJSON;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace Gj
{
    public enum DateAction
    {
        Null,
        Timer,
        CountDown
    }

    /*
     * 设置启动时间，设置总时间，打开end 用来做倒计时
     * 设定启动时间，打开end 用来做计时
     */
    public class DateHelper : NodeHelper
    {
        public string format = "yyyy-MM-dd HH:mm:ss";
        public DateAction dateAction = DateAction.Null;
        public bool hide;
        public bool end;
        public bool number;
        public bool time;
        public bool ms;
        public bool all;
        public bool pro;
        public bool dateTime = true;
        public int tipTime;
        private Text _Text;
        private TextMeshProUGUI _TextPro;
        public TextHelper TextHelper;
        private Text Text
        {
            get
            {
                if (_Text == null) _Text = GetComponent<Text>();
                return _Text;
            }
        }

        private TextMeshProUGUI TextPro
        {
            get
            {
                if (_TextPro == null) _TextPro = GetComponent<TextMeshProUGUI>();
                return _TextPro;
            }
        }
        public Image Image;
        public Slider Slider;
        public AudioClip clip;
        public SoundType soundType;
        public NodeHelper[] list;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey totalKey;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey startKey;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey endKey;
        [SelectRef(UIKey.DATA_KEY)] public SelectKey customKey;

        public GameObject obj;
        private int _t = -1;
        private DateTime date;
        private int step;
        private int total;
        private bool open;

        protected override BindDataType bindDataType =>
            all ? BindDataType.All : BindDataType.Int;

        // private void OnDisable()
        // {
        //     Close();
        // }
        //
        // private void OnEnable()
        // {
        //     Open();
        // }

        protected override void Init()
        {
            base.Init();
            switch (dateAction)
            {
                case DateAction.CountDown:
                    step = -1;
                    break;
                case DateAction.Timer:
                    step = 1;
                    break;
            }
        }

        public override void SetData(JSONObject json)
        {
            if (!totalKey.IsEmpty()) total = totalKey.Get(json);
            base.SetData(json);
        }

        protected override void BindData(JSONObject obj)
        {
            var start = startKey.Get(obj).AsInt;
            if (!endKey.IsEmpty())
            {
                var end = endKey.Get(obj).AsInt;
                total = end - start;
            }

            BindData((customKey.IsEmpty() ? (dateTime ? DateTools.GetNowTime() : (int)Time.time) : customKey.Get(obj).AsInt) - start);
        }

        protected override void BindData(double d)
        {
            SetData((float)(d / 1000));
        }

        protected override void BindData(int t)
        {
            if (_t == t) return;
            _t = t;
            int _time = t;
            if (end) _time = _time - (dateTime ? DateTools.GetNowTime() : (int)Time.time);
            if (total > 0 && dateAction == DateAction.CountDown) _time = total - _time;
            if (_time == 0 && dateAction == DateAction.CountDown) return;
            Close();
            // Debug.LogErrorFormat("BindData: {0} {1}",_time, total);
            date = ms ? DateTools.GetDateByMilli(_time) : DateTools.GetDate(_time);
            var time = (int)(date - DateTools.GetZero()).TotalSeconds;
            switch (dateAction)
            {
                case DateAction.Timer:
                    Open();
                    break;
                case DateAction.CountDown:
                    CheckTipTime(time < tipTime);
                    Open();
                    break;
                case DateAction.Null:
                    break;
            }

            if (hide) gameObject.SetActive(true);

            UpdateImage();
            UpdateSlider();
            UpdateText();
        }

        private void Open()
        {
            if (debug) Debug.LogError("Date Open");
            InvokeRepeating("RefreshDate", 1, 1);
            open = true;
        }

        private void Close()
        {
            if (debug) Debug.LogError("Date Close");
            CancelInvoke("RefreshDate");
            open = false;
        }


        private void RefreshDate()
        {
            var time = DateTools.GetTime(date);
            
            UpdateImage();
            UpdateSlider();
            UpdateText();

            date = date.AddSeconds(step);
            
            if (dateAction == DateAction.CountDown)
            {
                CheckTipTime(time < tipTime);
                if (time <= 0)
                {
                    TimeOut();
                    Close();
                    return;
                }
            }

            if (dateAction == DateAction.Timer)
            {
                CheckTipTime(total > 0 && total - time < tipTime);
                if (time >= total && total > 0)
                {
                    TimeOut();
                    Close();
                    return;
                }
            }

            if (soundType != SoundType.None)
                Game.single.PlayEFF(soundType);
            else if (clip != null) Game.single.PlayEFF(clip);
        }

        private void TimeOut()
        {
            if (obj != null) obj.SendMessage("TimeOut");
            Emit(UIEvent.TimeOut);
            if (hide)
            {
                gameObject.SetActive(false);
            }
            else
            {
                UpdateImage();
                UpdateSlider();
                UpdateText();
            }
        }

        private void UpdateText()
        {
            var t = DateTools.GetTime(date);
            if (t == 0 && TextHelper != null)
                SetText("");
            else
            {
                if (number)
                {
                    SetText(t.ToString());
                }
                else if (time)
                {
                    var hour = t / 3600;
                    var min = (t - hour * 3600) / 60;
                    var sen = t - hour * 3600 - min * 60;
                    SetText(string.Format("{0:d2}:{1:d2}:{2:d2}", hour, min, sen));
                }
                else if (format != "")
                {
                    SetText(date.ToString(format));
                }
            }
        }

        private void SetText(string s)
        {
            if (TextHelper != null)
            {
                TextHelper.SetData(s);
            }
            else if (pro && TextPro != null)
            {
                TextPro.text = s;
            }
            else if (Text != null)
            {
                Text.text = s;
            }
        }

        private void UpdateSlider()
        {
            if (Slider == null) return;
            Slider.value = DateTools.GetTime(date) / (float)total;
        }

        private void UpdateImage()
        {
            if (Image == null) return;
            // Debug.LogErrorFormat("{0} {1}", DateTools.GetTime(date), total);
            Image.fillAmount = DateTools.GetTime(date) / (float)total;
        }

        private void CheckTipTime(bool b)
        {
            if (b)
                soundType = SoundType.TimeOut;
            else
                soundType = SoundType.None;

            for (var i = 0; i < list.Length; i++) list[i].SetData(b);
        }
    }
}